<template>
  <div class="index">
    <div class="msg-header">
      <LoginHeader>
        <template #default>
             V信群聊 
            (<span>{{online}}</span>人在线)
         </template>
        <template #left>
          <van-icon name="arrow-left" @click="logout" />
        </template>

        <template #right>
          <span style="font-size: 14px; color: #f3f3f3" v-if="$store.getters.getUserInfo"> {{$store.getters.getUserInfo.name}}</span>
        </template>
      </LoginHeader>
    </div>

    <div class="msg-box" ref="msgBox">
      <template v-for="(item, index) in msgBox">

        <template v-if="item.cmdType == 0"> 
            <div class="msg-item sys-msg"  :key="index" ref="msgItem">
                <div class="times">{{item.sendTime}}</div>
                <span v-html="item.msg"> </span>
            </div>
        </template>

        <template v-if="item.cmdType ==1"> 
           
            <div class="msg-item me-msg"  :key="index" ref="msgItem">
               <div>
                    <span class="sender-box"> {{item.sender}}</span>
                    <span class="times-box"> ({{item.sendTime}}): </span>
                </div>
                <div class="msg-content" v-html="item.msg"></div>
            </div>
        </template>

        <template v-if="item.cmdType == 2"> 
           <div class="msg-item you-msg"  :key="index" ref="msgItem">
                    <div>
                         <span class="sender-box"> {{item.sender}}</span>
                         <span class="times-box"> ({{item.sendTime}}): </span>
                    </div>
                    <div class="msg-content" v-html="item.msg"></div>
                </div>
           
        </template>
      </template>

    </div>

      

    <div class="msg-floot">
      <div class="bq-box" @click="syncOpenBox('extBox')">
        <i class="iconfont icon-add-o" style="font-size: 30px"></i>
      </div>
      <div class="input-box">
        <input type="text" v-model="sendEntity.text" @keydown.enter="sendMsg" />
      </div>
      <div class="btn-box">
        <span @click="syncOpenBox('bqBox')">
          <svg
            t="1613874887616"
            class="icon"
            viewBox="0 0 1024 1024"
            version="1.1"
            xmlns="http://www.w3.org/2000/svg"
            p-id="7427"
            width="30"
            height="30"
          >
            <path
              d="M512 959.1c-114.6 0-229.1-43.6-316.3-130.9-174.3-174.4-174.2-458.1 0.2-632.4C298.7 93 445.6 46.6 589 71.5c14.3 2.5 23.9 16.1 21.4 30.4-2.5 14.3-16.1 23.9-30.4 21.4-126.5-22-256.2 19-347 109.7-153.9 153.8-154 404.2-0.2 558.1 153.8 153.9 404.2 154 558.1 0.2s154-404.2 0.2-558.2c-15.4-15.4-32-29.5-49.6-42.1-11.8-8.5-14.5-24.9-6-36.7 8.5-11.8 24.9-14.5 36.7-6 19.8 14.2 38.7 30.3 56.1 47.7 174.3 174.4 174.2 458.1-0.2 632.5-87.1 87-201.6 130.6-316.1 130.6z"
              p-id="7428"
            ></path>
            <path
              d="M312.8 410.7m-42.8 0a42.8 42.8 0 1 0 85.6 0 42.8 42.8 0 1 0-85.6 0Z"
              p-id="7429"
            ></path>
            <path
              d="M715.6 410.9m-42.5 0a42.5 42.5 0 1 0 85 0 42.5 42.5 0 1 0-85 0Z"
              p-id="7430"
            ></path>
            <path
              d="M281.1 553.2v0.4c0 127.5 103.3 231 230.9 231s231-103.3 231-230.9v-0.4l-461.9-0.1z"
              fill="#FFA786"
              p-id="7431"
            ></path>
            <path
              d="M512 810.9s-0.1 0 0 0c-141.9 0-257.3-115.5-257.2-257.3 0-7.9 3.2-26.2 32.7-26.3h82.4c67.1 0 160.4 0 236.9 0.1l133.6 0.1c28.6 0.1 28.9 26 28.9 26.3-0.1 141.7-115.5 257.1-257.3 257.1zM309 579.8c12.9 100.5 99 178.5 202.9 178.5h0.1c103.9 0 190-77.9 203-178.4-82.1 0-324-0.1-406-0.1z"
              p-id="7432"
            ></path>
            <path
              d="M673.4 124.4m-26.3 0a26.3 26.3 0 1 0 52.6 0 26.3 26.3 0 1 0-52.6 0Z"
              fill="#FFA786"
              p-id="7433"
            ></path>
          </svg>
        </span>
        <van-button type="primary" size="small" @click="sendMsg">发送</van-button>
      </div>
    </div>

    <!-- 表情包 -->
    <div class="bq-container2" v-show="boxFlag == 'bqBox'">
      <span class="close-btn" @click="boxFlag = ''"
        ><van-icon name="cross" style="font-size: 20px"
      /></span>

      <div class="container">
        <div
          class="bq-item"
          @click="bgItemClick(item.flag)"
          v-for="(item, index) in bgImgs"
          :key="index"
        >
          <img :src="item.img" />
        </div>
      </div>
    </div>

    <!-- 扩展操作[发送图片、语音、红包...]  -->
    <div class="extra-container" v-if="boxFlag == 'extBox'">
        <van-uploader  :after-read="afterRead">
            <div class="item">
                <p>
                <span
                    class="iconfont icon-xiangce-copy"
                    style="font-size: 35px"
                ></span>
                </p>
                <p>相册</p>
            </div>
      </van-uploader>

      <div class="item">
        <p><span class="iconfont icon-yuyin" style="font-size: 35px"></span></p>
        <p>语音</p>
      </div>
    </div>
  </div>
</template>

<script>
import { Dialog,Toast } from "vant";
import LoginHeader from "@/components/LoginHeader";
import {SocketServer,EventType} from '@/server/SocketServer'
import MessageHandler,{ Event } from '@/server/MessageEventHandler'
export default {
  name: "index",
  components: {
    LoginHeader,
  },
  data() {
    return {
        online:0,
      msgBox: [],
      bgImgs: [],
      boxFlag: "",
      sendEntity: {
        text: "",
      },
      socketServer:null,
      heartInterval:null
    };
  },
 async created() {
    var token = sessionStorage.getItem("token");
    if(!token){
        this.$router.push({
          name:"/login"
        })
    }

    var userInfo = await this.getUserInfo();
    if(!userInfo||!userInfo.name){
      let flag = false;
      do{
        var name = prompt('请输入你的名称');
        const res = await this.setUserName(name)
        if(res.data.code == 200){
          flag=true;
        }else{
          alert(res.data.msg)
        }
      }while(!flag);
    
       userInfo = await this.getUserInfo();
    }
    this.$store.commit('setUserInfo',userInfo);

    this.initSocket(token);


    for (var i = 1; i <= 132; i++) {
      this.bgImgs.push({
        flag: i,
        img: require(`../assets/bq/${i}.gif`),
      });
    }
  },
  destroyed() {
    this.cleanHeartInterval();
  },
  methods: {
    sendMsg(){
      if(!this.sendEntity.text||this.sendEntity.text.length === 0){
          Toast({
            message: "发送内容不能为空",
            position: 'top',
            });
          return;
      }
       let msg={
          cmdType:2,
          msg:this.sendEntity.text 

        };
        this.socketServer.sendMsg(JSON.stringify(msg));
        this.sendEntity.text="";
    },
    setUserName(name){
      console.log(name)
      return new Promise((resolve,reject)=>{
        this.$server.user.setUserName(name).then(res=>{
          const { data } = res;
          resolve(data)
        }).catch( )
      })
    },
    initSocket(token){
      const handler = new MessageHandler();
      handler.registeEvent(Event.FLUSH_MESSAGE,this.renderMsg);
      handler.registeEvent(Event.FLUSH_ONLINE,this.flushOnline);
      handler.registeEvent(Event.FLUSH_ONLINE_LIST,this.flushOnlineList);

        var $t = this;
         // 初始化 
        var s = this.socketServer = new SocketServer('ws://localhost:10086/ws');
        s.registeEvent(EventType.OPEN,function(e){
          var cmdData = {
            cmdType:1,
            name:$t.$store.getters.getUserInfo.name
          }
          console.log(s)
          s.sendMsg(JSON.stringify(cmdData));
          $t.initHeartPongMsgPack(s.getTarget());
        });

         s.registeEvent(EventType.ERROR,function(e){
            console.log(e)
            $t.cleanHeartInterval();
        });


        s.registeEvent(EventType.MESSAGE,function(messageEvent){
            const { data, target: ws } = messageEvent;
              let msgObj = JSON.parse(data);
              handler.handle(msgObj)
        });

        s.registeEvent(EventType.CLOSE,function(){
            console.log('close')
            $t.cleanHeartInterval();
        });
    },
    cleanHeartInterval(){
      if(this.heartInterval){
        clearInterval(this.heartInterval)
      }
    },
      initHeartPongMsgPack(ws){
        if(this.heartInterval){
            clearInterval(this.heartInterval)
        }
      this.heartInterval = setInterval(()=>{
        var cmdData = {
          cmdType: 101,
        };
        try {
          ws.send(JSON.stringify(cmdData))
        } catch (error) {
           clearInterval(this.heartInterval);
           console.log(`心跳发送失败，连接断开，任务已关闭`)
        }
      },7000);

    },
    checkAndScrollDown(){
      
      this.$nextTick(()=>{
        this.$refs['msgBox'].lastElementChild.scrollIntoView()
      })
    },
    // 渲染消息到聊天框
    renderMsg(msgObj){
      this.formatMessage(msgObj);
      this.msgBox.push(msgObj);
      this.checkAndScrollDown();
    },
    // 刷新在线人数
    flushOnline(msgObj){
      this.online = msgObj.online;
    },
     // 刷新在线人员列表
    flushOnlineList(msgObj){
      console.log(msgObj.onlineList)

    },
    formatMessage(msgObj){
      let reg1 = /\[&bq#(\d{1,3})\]/gim
      let msg = "";

      let start = 0;
      let res;
      while(true){
          res = reg1.exec(msgObj.msg)
          if(res == null){
            break;
          }
         msg+= msgObj.msg.substring(start,res.index);
         let IMG = require(`@/assets/bq/${res[1]}.gif`);
         msg+=`<img src='${IMG}' />`;
         start = res[0].length+res.index
      }

      if(start < msgObj.msg.length){
        msg+=msgObj.msg.substring(start)
      }

      msgObj.msg=msg
    },
    getUserInfo(token){
      return new Promise((resolve,reject)=>{
         this.$server.user.getUserInfo().then(res=>{
           const { data } = res;
           if(data.code == 200){
               resolve(data.data)
           }else{
             reject(data.msg);
           }
         }).catch(reject)
      })

    },
    afterRead(file){
        
        console.log(file)
    },
    logout() {
      Dialog.confirm({
        title: "退出用户",
        message: "确认要退出群聊吗",
      })
        .then(() => {
           this.socketServer.close();
          // on confirm
          this.$router.push({ name: "login" });
        })
        .catch(() => {});
    },
    formatImgFlag(flag) {
      return `[&bq#${flag}]`;
    },
    bgItemClick(flag) {
      this.sendEntity.text = this.sendEntity.text + this.formatImgFlag(flag);
    },
    syncOpenBox(flag) {
      if (this.boxFlag == flag) {
        this.boxFlag = "";
      } else {
        this.boxFlag = flag;
      }
    },
  },
};
</script>

<style lang="less" scoped>
@import "../assets/font_2379421/iconfont.css";
.index {
  height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .msg-header {
    height: 50px;
    background-image: linear-gradient(135deg, #2afadf 10%, #4c83ff 100%);
  }
  .msg-box {
    flex: 1;
    background-color: #f3f3f3;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 5px;

    .msg-item {
      padding: 5px;

      &.you-msg {
        text-align: left;
        .sender-box {
          color: #5abc6a;
          text-shadow: 0 0 1px #5abc6a;
        }
        .times-box {
          color: rgb(159, 160, 161);
        }

        .msg-content {
          word-break: break-all;
          display: inline-block;
          text-align: left;
          max-width: 70%;
          border: none;
          border-radius: 4px;
          min-height: 35px;
          background-color: #ffffff;
          padding: 8px 15px;
          box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
        }
      }

      &.me-msg {
        text-align: right;
        .sender-box {
          color: dodgerblue;
          text-shadow: 0 0 2px dodgerblue;
        }
        .times-box {
          color: rgb(159, 160, 161);
        }
        .msg-content {
          display: inline-block;
          text-align: left;
          max-width: 70%;
          border: none;
          border-radius: 4px;
          min-height: 35px;
          background-color: #8ddd62;
          padding: 8px 15px;
        }
      }

      &.sys-msg {
        text-align: center;
        .times {
          font-size: 13px;
          font-weight: 100;
          color: dimgray;
        }
        span {
          border: 1px solid transparent;
          border-radius: 4px;
          padding: 2px 15px;
          background-color: rgb(224, 221, 221);
          color: #747070ef;
        }
      }
    }
  }
  .msg-floot {
    height: 50px;
    line-height: 50px;
    background-color: rgb(233, 231, 231);
    border-top: 1px solid #ccc;
    position: relative;
    .bq-box {
      position: absolute;
      left: 0;
      height: inherit;
      line-height: 50px;
      width: 50px;
      padding-left: 10px;
      i {
        position: relative;
        font-weight: 900;
        cursor: pointer;
      }
    }
    .input-box {
      position: absolute;
      height: inherit;
      left: 50px;
      right: 100px;
      padding: 1px 4px;
      input[type="text"] {
        width: 100%;
        height: 30px;
        border: none;
        border-radius: 4px;
        padding: 1px 4px;
        font-size: 14px;
      }
    }
    .btn-box {
      position: absolute;
      right: 0;
      width: 100px;
      height: inherit;
      padding: 10px 4px;
      .van-button {
        position: relative;
        top: -15px;
        left: 10px;
        padding-left: 10px;
        padding-right: 10px;
      }
    }
  }

  .bq-container2 {
    position: absolute;
    bottom: 50px;
    background-color: #fff;
    width: 100%;

    .container {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      max-height: 138px;
      overflow-y: auto;

      .bq-item {
        width: 35px;
        height: 35px;
        border: 1px solid #f3f3f3;
        text-align: center;
        padding-top: 4px;

        &:hover {
          border-color: #4c83ff;
        }
      }
    }

    .close-btn {
      display: inline-block;
      width: 30px;
      height: 30px;
      position: absolute;
      right: 0;
      top: -30px;
      z-index: 999;
      background-color: rgba(0, 0, 0, 0.2);
      color: #fff;
      padding: 5px;
    }
  }

  .extra-container {
    position: absolute;
    bottom: 50px;
    background-color: rgb(214, 214, 214);
    width: 100%;
    min-height: 60px;
    padding: 15px;

    .item {
      display: inline-block;
      border: none;
      width: 60px;
      height: 60px;
      background-color: #fff;
      border-radius: 8px;
      text-align: center;
      border: 1px solid transparent;

      &:not(.item:nth-child(1)){
          margin-left: 20px;
      }
      p {
        margin: 0;
        padding: 0;

        &:nth-child(2) {
          font-size: 13px;
        }
      }
      &:active {
        border-color: tomato;
      }
    }
  }
}
</style>